Part 6. 캡슐화
58개 중 2개. 중요한 데이터 또는 기능성을 불충분하게 캡슐화하였을 때, 인가되지 않은 사용자에게 데이터 누출이 가능해지는 보안약점. 관통 질문: 개발 중에만 필요했던 것이 배포본에 남아 있지 않은가?
1. 제거되지 않고 남은 디버그 코드 CWE-489
신뢰 경계: 개발 단계 디버그 출력/진입점 → 제거 없이 → 배포 빌드 ⚠️ 디버그 코드는 “지우거나 ifdef로 감싸거나” 둘 중 하나다. 그냥 두는 선택지는 없다.
공격 시나리오: 디버그 진입점은 인증을 거치지 않는 경우가 많아 공격자에게 그대로 백도어가 되고, 식별·인증 과정을 우회당한다.
❌ Bad
int main()
{
puts("Debug message"); /* 배포본에 남은 디버그 출력 */
}✅ Good
#ifdef DEBUG_ENABLE
#define DEBUG(message) { puts( message ); }
#else
#define DEBUG(message) /* 배포 시 아무것도 안 함 */
#endif
int main() { DEBUG("Debug message"); }치환 규칙: 디버그 출력·콘솔은 전부 제거하거나 #ifdef DEBUG_ENABLE 조건부 컴파일로 감싸 릴리스 빌드에서 제외, 배포 전 소스 검색으로 잔존 여부 점검.
2. 시스템 데이터 정보노출 CWE-497
신뢰 경계: 환경변수·내부 경로 → 그대로 → 예외/에러 메시지 화면 출력 ⚠️ 에러 메시지는 “사용자용(일반화)“과 “운영자용(상세 로그)“을 물리적으로 분리하라.
공격 시나리오: PATH·경로·DB 접속 정보 같은 내부 데이터가 노출되면 공격자가 후속 공격의 표적과 경로를 정밀하게 설계할 수 있다.
❌ Bad
char* path = getenv("PATH");
fprintf(stderr, "cannot find exe on path %s\n", path); /* 경로 정보 그대로 노출 */✅ Good
char* path = getenv("PATH");
fprintf(stderr, "cannot find exe on path \n"); /* 내부 경로 제외한 일반 메시지 */치환 규칙: 예외 상황에서도 환경변수·경로·스택 정보를 오류 메시지에 포함하지 않는다 — 상세 정보는 접근 통제된 내부 로그로만.
Part 6 미니 체크리스트
- 배포 빌드에
puts/printf형태의 디버그 출력이 남아 있는가 -
#ifdef DEBUG_ENABLE로 감싸지 않은 디버그 진입점(숨은 명령·백도어 성격)이 있는가 - 에러 메시지에 환경변수·경로·스택 정보가 그대로 노출되는가
- 릴리스 바이너리에서 디버그 심볼이 제거(strip)되었는가
관련 노트
- 시큐어코딩가이드 목록
- Part 4. 에러 처리 — 오류 메시지 정보 노출과 같은 원인의 다른 표현
- Part 5. 코드 오류
- Part 7. API 오용